<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Config;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Composer;
use Illuminate\Support\Facades\DB;

class FunctionDeviceCommand extends Command {

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'make:functiondevice {function} {--model=} {--alias=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '创建一个新的功能模块';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct(Filesystem $filesystem, Composer $composer) {
        parent::__construct();

        $this->files = $filesystem;
        $this->composer = $composer;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle() {

        $this->writeFunction();
        //重新生成autoload.php文件
        $this->composer->dumpAutoloads();
    }

    private function writeFunction() {
        if ($this->createController()) {
            //若生成成功,则输出信息
            $this->info('Success to make a ' . ucfirst($this->argument('function')) . ' controller');
        }
        if ($this->createModel()) {
            //若生成成功,则输出信息
            $this->info('Success to make a ' . ucfirst($this->option('model')) . ' model');
        }
        if ($this->createView()) {
            //若生成成功,则输出信息
            $this->info('Success to make a ' . ucfirst($this->option('model')) . ' view');
        }
        if ($this->createRoute()) {
            //若生成成功,则输出信息
            $this->info('Success to make a ' . ucfirst($this->argument('function')) . ' Route');
        }
        if ($this->createDB()) {
            //若生成成功,则输出信息
            $this->info('Success to make a ' . ucfirst($this->argument('function')) . ' DB');
        }


    }

    private function getPath($name) {
        // 两个模板文件,对应的两个路径
        $path = null;
        switch ($name) {
            case 'controller':
                $argument = $this->argument('function');
                $path = $this->getDirectory($name) . DIRECTORY_SEPARATOR . $this->setController($argument) . '.php';
                break;
            case 'model':
                $model = $this->option('model');
                $path = $this->getDirectory($name) . DIRECTORY_SEPARATOR . $model . '.php';
                break;
            case 'viewindex':
                $argument = $this->argument('function');
                $path = $this->getDirectory($name).$argument.DIRECTORY_SEPARATOR;
                $this->makeDirectory($path);
                $path = $path  . 'index.blade.php';
                break;
            case 'viewsave':
                $argument = $this->argument('function');

                $path = $this->getDirectory($name).$argument.DIRECTORY_SEPARATOR;
                $this->makeDirectory($path);
                $path = $path  . 'save.blade.php';
                break;
        }

        return $path;
    }

    private function getTemplateData($name) {

        //获取function和model两个参数值
        $argument = $this->argument('function');
        $option = $this->option('model');
        $as = $this->option('alias');

        $templateVar = [];

        switch ($name) {
            case 'controller':
                $templateVar = [
                    'ControllerName' => $this->setController($argument),
                    'ModelName'      => $option,
                    'Alias'          => $as,
                    'Name'           => $this->humpToLine($argument),
                    'View'           => $argument,
                ];
                break;
            case 'model':
                $templateVar = [
                    'ModelName' => $option,
                    'Alias'     => $as,
                    'DBName'    => "'".$this->humpToLine($option)."'",
                ];
                break;
            case 'viewindex':
                $templateVar = [
                    'ModelName'      => $option,
                    'Alias'          => $as,
                    'Name'           => $this->humpToLine($argument),
                    'View'           => $argument,
                ];
                break;
            case 'viewsave':
                $templateVar = [
                    'ModelName'      => $option,
                    'Alias'          => $as,
                    'Name'           => $this->humpToLine($argument),
                    'View'           => $argument,
                ];
                break;

        }

        return $templateVar;
    }

    private function createDB() {

        $argument = $this->argument('function');
        $as = $this->option('alias');
        $name = $this->humpToLine($argument);

        $count = DB::table('admin_note')->where('admin_note_parent_id','=',0)->count();

        $admin_note_sort = ($count+1)*10;

        $id = DB::table('admin_note')->insertGetId([
            'admin_note_name' => $as.'管理',
            'admin_note_zh_name' =>$as.'管理',
            'admin_note_controller' => 'admin_'.$name.'_index',
            'admin_note_action' => 'admin_'.$name.'_save,admin_'.$name.'_del,admin_'.$name.'_status',
            'admin_admin_show' => 0,
            'admin_note_parent_id' => 0,
            'admin_note_sort' => $admin_note_sort,
            'admin_note_show' => 1,
            'admin_has_subset'=>0,
            'admin_note_created_time' => time(),
            'admin_note_updated_time' => time(),
        ]);
        DB::table('admin_note')->insert([
            'admin_note_name' => '编辑'.$as,
            'admin_note_zh_name' =>$as.'管理-编辑'.$as,
            'admin_note_controller' => 'admin_'.$name.'_save',
            'admin_note_action' => 'admin_'.$name.'_index',
            'admin_admin_show' => 0,
            'admin_note_parent_id' => $id,
            'admin_note_sort' => $admin_note_sort+1,
            'admin_note_show' => 0,
            'admin_has_subset'=>0,
            'admin_note_created_time' => time(),
            'admin_note_updated_time' => time(),
        ]);
        DB::table('admin_note')->insert([
            'admin_note_name' => '删除'.$as,
            'admin_note_zh_name' =>$as.'管理-删除'.$as,
            'admin_note_controller' => 'admin_'.$name.'_del',
            'admin_note_action' => 'admin_'.$name.'_index',
            'admin_admin_show' => 0,
            'admin_note_parent_id' => $id,
            'admin_note_sort' => $admin_note_sort+2,
            'admin_note_show' => 0,
            'admin_has_subset'=>0,
            'admin_note_created_time' => time(),
            'admin_note_updated_time' => time(),
        ]);
        DB::table('admin_note')->insert([
            'admin_note_name' => $as.'状态编辑',
            'admin_note_zh_name' =>$as.'管理-'.$as.'状态编辑',
            'admin_note_controller' => 'admin_'.$name.'_status',
            'admin_note_action' => 'admin_'.$name.'_index',
            'admin_admin_show' => 0,
            'admin_note_parent_id' => $id,
            'admin_note_sort' => $admin_note_sort+3,
            'admin_note_show' => 0,
            'admin_has_subset'=>0,
            'admin_note_created_time' => time(),
            'admin_note_updated_time' => time(),
        ]);
    }

    private function createRoute() {

        $argument = $this->argument('function');
        $option = $this->option('model');
        $as = $this->option('alias');
        $controller = $this->setController($argument);
        $name = 'admin_'.$this->humpToLine($argument);
        $nameindex = $name.'_index';
        $namesave = $name.'_save';
        $namedel = $name.'_del';
        $namestatus = $name.'_status';
        $route = $this->files->get($this->getDirectory('route'));
        $routes = explode('});',$route);
        $end = count($routes)-1;
        unset($routes[count($routes)-2]);
        $routes[$end] = "
        
//----------------$as-------------------------
    Route::group(['prefix'=>'$argument'], function () {
        Route::match(array('post','get'),'/index.html', 'Backstage\\$controller@index')->name('$nameindex');
 
        Route::match(array('post','get'),'/save.html', 'Backstage\\$controller@save')->name('$namesave');

        Route::post('/del.html', 'Backstage\\$controller@del')->name('$namedel');
        
        Route::post('/status.html', 'Backstage\\$controller@status')->name('$namestatus');

    ";
        $routes[] = " 


";
        $routes[] = "";
        $routes = implode('});',$routes);

        return $this->files->put($this->getDirectory('route'),$routes);
    }

    private function createView() {

        $this->createDirectory('viewindex');
        $this->createClass('viewindex');
        $this->createClass('viewsave');
        return true;
    }

    private function createModel() {

        $this->createDirectory('model');

        return $this->createClass('model');
    }

    private function createController() {

        $this->createDirectory('controller');

        return $this->createClass('controller');
    }

    private function createDirectory($name) {
        $directory = $this->getDirectory($name);
        //检查路径是否存在,不存在创建一个,并赋予775权限
        if (!$this->files->isDirectory($directory)) {
            return $this->files->makeDirectory($directory, 0755, true);
        }
    }

    private function makeDirectory($directory){
        if (!$this->files->isDirectory($directory)) {
            return $this->files->makeDirectory($directory, 0755, true);
        }
    }

    private function getDirectory($name) {

        return Config::get('functionpath.' . $name);
    }

    private function createClass($name) {
        //渲染模板文件,替换模板文件中变量值
        $templates = $this->templateStub($name);

        $class = $this->files->put($this->getPath($name), $templates);

        return $class;
    }

    private function templateStub($name) {
        $stub = $this->getStub($name);
        // 获取需要替换的模板文件中变量
        $templateData = $this->getTemplateData($name);

        return $this->getRenderStub($templateData, $stub);
    }

    private function getStub($name) {


        return $this->files->get(resource_path('stubs') . DIRECTORY_SEPARATOR . 'stub' . $name . '.stub');
    }

    private function setController($argument) {
        return $argument . 'Controller';
    }

    private function getRenderStub($templateData, $stub) {

        foreach ($templateData as $search => $replace) {
            $stub = str_replace('$' . $search, $replace, $stub);
        }

        return $stub;
    }

    /*
     * 驼峰转下划线
     */
    private function humpToLine($str) {

        return strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $str));
    }


}
